import requests
import json
import pandas as pd  # type:ignore
from concurrent.futures import ThreadPoolExecutor, wait, FIRST_COMPLETED, ALL_COMPLETED
from typing import Literal, List, Generator, Any, Tuple, cast, Callable
import requests
from bs4 import BeautifulSoup, Tag as bs4tag  # type:ignore
import re
from copy import deepcopy
from functools import lru_cache
import os
import time
import execjs

class Macklin():
    """麦克林爬虫"""

    def __init__(self, brandIds: List[int] = [], max_workers: int = 10) -> None:
        self.header = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0",
        }
        self.macklinDomain = "https://www.macklin.cn/"
        self.macklinSession = requests.Session()
        self.macklinSession.headers.update(self.header)
        self.macklinSession.headers.update(
            {
                "Origin": "https://www.macklin.cn",
                "X-Agent": "web",
                "X-Language": "cn",
                "X-Timestamp": "1721377558",
                "X-User-Token": "",
            }
        )

        self.hashfunc = execjs.compile(
            """
            function fd(t, e) {
                const a = (65535 & t) + (65535 & e)
                  , i = (t >> 16) + (e >> 16) + (a >> 16);
                return i << 16 | 65535 & a
            }
            function vd(t, e) {
                return t << e | t >>> 32 - e
            }
            function Ad(t, e, a, i, s, o) {
                return fd(vd(fd(fd(e, t), fd(i, o)), s), a)
            }
            function _d(t, e, a, i, s, o, r) {
                return Ad(e & a | ~e & i, t, e, s, o, r)
            }
            function bd(t, e, a, i, s, o, r) {
                return Ad(e & i | a & ~i, t, e, s, o, r)
            }
            function yd(t, e, a, i, s, o, r) {
                return Ad(e ^ a ^ i, t, e, s, o, r)
            }
            function wd(t, e, a, i, s, o, r) {
                return Ad(a ^ (e | ~i), t, e, s, o, r)
            }
            function xd(t, e) {
                t[e >> 5] |= 128 << e % 32,
                t[14 + (e + 64 >>> 9 << 4)] = e;
                let a, i, s, o, r, n = 1732584193, l = -271733879, c = -1732584194, d = 271733878;
                for (a = 0; a < t.length; a += 16)
                    i = n,
                    s = l,
                    o = c,
                    r = d,
                    n = _d(n, l, c, d, t[a], 7, -680876936),
                    d = _d(d, n, l, c, t[a + 1], 12, -389564586),
                    c = _d(c, d, n, l, t[a + 2], 17, 606105819),
                    l = _d(l, c, d, n, t[a + 3], 22, -1044525330),
                    n = _d(n, l, c, d, t[a + 4], 7, -176418897),
                    d = _d(d, n, l, c, t[a + 5], 12, 1200080426),
                    c = _d(c, d, n, l, t[a + 6], 17, -1473231341),
                    l = _d(l, c, d, n, t[a + 7], 22, -45705983),
                    n = _d(n, l, c, d, t[a + 8], 7, 1770035416),
                    d = _d(d, n, l, c, t[a + 9], 12, -1958414417),
                    c = _d(c, d, n, l, t[a + 10], 17, -42063),
                    l = _d(l, c, d, n, t[a + 11], 22, -1990404162),
                    n = _d(n, l, c, d, t[a + 12], 7, 1804603682),
                    d = _d(d, n, l, c, t[a + 13], 12, -40341101),
                    c = _d(c, d, n, l, t[a + 14], 17, -1502002290),
                    l = _d(l, c, d, n, t[a + 15], 22, 1236535329),
                    n = bd(n, l, c, d, t[a + 1], 5, -165796510),
                    d = bd(d, n, l, c, t[a + 6], 9, -1069501632),
                    c = bd(c, d, n, l, t[a + 11], 14, 643717713),
                    l = bd(l, c, d, n, t[a], 20, -373897302),
                    n = bd(n, l, c, d, t[a + 5], 5, -701558691),
                    d = bd(d, n, l, c, t[a + 10], 9, 38016083),
                    c = bd(c, d, n, l, t[a + 15], 14, -660478335),
                    l = bd(l, c, d, n, t[a + 4], 20, -405537848),
                    n = bd(n, l, c, d, t[a + 9], 5, 568446438),
                    d = bd(d, n, l, c, t[a + 14], 9, -1019803690),
                    c = bd(c, d, n, l, t[a + 3], 14, -187363961),
                    l = bd(l, c, d, n, t[a + 8], 20, 1163531501),
                    n = bd(n, l, c, d, t[a + 13], 5, -1444681467),
                    d = bd(d, n, l, c, t[a + 2], 9, -51403784),
                    c = bd(c, d, n, l, t[a + 7], 14, 1735328473),
                    l = bd(l, c, d, n, t[a + 12], 20, -1926607734),
                    n = yd(n, l, c, d, t[a + 5], 4, -378558),
                    d = yd(d, n, l, c, t[a + 8], 11, -2022574463),
                    c = yd(c, d, n, l, t[a + 11], 16, 1839030562),
                    l = yd(l, c, d, n, t[a + 14], 23, -35309556),
                    n = yd(n, l, c, d, t[a + 1], 4, -1530992060),
                    d = yd(d, n, l, c, t[a + 4], 11, 1272893353),
                    c = yd(c, d, n, l, t[a + 7], 16, -155497632),
                    l = yd(l, c, d, n, t[a + 10], 23, -1094730640),
                    n = yd(n, l, c, d, t[a + 13], 4, 681279174),
                    d = yd(d, n, l, c, t[a], 11, -358537222),
                    c = yd(c, d, n, l, t[a + 3], 16, -722521979),
                    l = yd(l, c, d, n, t[a + 6], 23, 76029189),
                    n = yd(n, l, c, d, t[a + 9], 4, -640364487),
                    d = yd(d, n, l, c, t[a + 12], 11, -421815835),
                    c = yd(c, d, n, l, t[a + 15], 16, 530742520),
                    l = yd(l, c, d, n, t[a + 2], 23, -995338651),
                    n = wd(n, l, c, d, t[a], 6, -198630844),
                    d = wd(d, n, l, c, t[a + 7], 10, 1126891415),
                    c = wd(c, d, n, l, t[a + 14], 15, -1416354905),
                    l = wd(l, c, d, n, t[a + 5], 21, -57434055),
                    n = wd(n, l, c, d, t[a + 12], 6, 1700485571),
                    d = wd(d, n, l, c, t[a + 3], 10, -1894986606),
                    c = wd(c, d, n, l, t[a + 10], 15, -1051523),
                    l = wd(l, c, d, n, t[a + 1], 21, -2054922799),
                    n = wd(n, l, c, d, t[a + 8], 6, 1873313359),
                    d = wd(d, n, l, c, t[a + 15], 10, -30611744),
                    c = wd(c, d, n, l, t[a + 6], 15, -1560198380),
                    l = wd(l, c, d, n, t[a + 13], 21, 1309151649),
                    n = wd(n, l, c, d, t[a + 4], 6, -145523070),
                    d = wd(d, n, l, c, t[a + 11], 10, -1120210379),
                    c = wd(c, d, n, l, t[a + 2], 15, 718787259),
                    l = wd(l, c, d, n, t[a + 9], 21, -343485551),
                    n = fd(n, i),
                    l = fd(l, s),
                    c = fd(c, o),
                    d = fd(d, r);
                return [n, l, c, d]
            }
            function kd(t) {
                let e, a = "";
                for (e = 0; e < 32 * t.length; e += 8)
                    a += String.fromCharCode(t[e >> 5] >>> e % 32 & 255);
                return a
            }
            function Id(t) {
                let e, a = [];
                for (a[(t.length >> 2) - 1] = void 0,
                e = 0; e < a.length; e += 1)
                    a[e] = 0;
                for (e = 0; e < 8 * t.length; e += 8)
                    a[e >> 5] |= (255 & t.charCodeAt(e / 8)) << e % 32;
                return a
            }
            function Cd(t) {
                return kd(xd(Id(t), 8 * t.length))
            }
            function Sd(t, e) {
                let a, i, s = Id(t), o = [], r = [];
                for (o[15] = r[15] = void 0,
                s.length > 16 && (s = xd(s, 8 * t.length)),
                a = 0; a < 16; a += 1)
                    o[a] = 909522486 ^ s[a],
                    r[a] = 1549556828 ^ s[a];
                return i = xd(o.concat(Id(e)), 512 + 8 * e.length),
                kd(xd(r.concat(i), 640))
            }
            function Dd(t) {
                let e, a, i = "0123456789abcdef", s = "";
                for (a = 0; a < t.length; a += 1)
                    e = t.charCodeAt(a),
                    s += i.charAt(e >>> 4 & 15) + i.charAt(15 & e);
                return s
            }
            function Bd(t) {
                return unescape(encodeURIComponent(t))
            }
            function Ed(t) {
                return Cd(Bd(t))
            }
            function Md(t) {
                return Dd(Ed(t))
            }
            function Qd(t, e) {
                return Sd(Bd(t), Bd(e))
            }
            function Fd(t, e) {
                return Dd(Qd(t, e))
            }
            const Pd = (t,e,a)=>e ? a ? Qd(e, t) : Fd(e, t) : a ? Ed(t) : Md(t)            
            function ji(t, e) {
                const a = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
                let i, s = [];
                if (e = e || a.length,
                t)
                    for (i = 0; i < t; i++)
                        s[i] = a[0 | Math.random() * e];
                else {
                    let t;
                    for (s[8] = s[13] = s[18] = s[23] = "-",
                    s[14] = "4",
                    i = 0; i < 36; i++)
                        s[i] || (t = 0 | 16 * Math.random(),
                        s[i] = a[19 == i ? 3 & t | 8 : t])
                }
                return s.join("")
            }
"""
        )
        self.timestamp = 0
        self.ServerTimestamp: int = 0
        self.ClentTimestamp: int = 0
        self.sign: str = ""
        self.clentinit()

    def hash_function(self, t, e=None, a=False):
        return self.hashfunc.call("Pd", t, e, a)

    def generateDeviceid(self, t, e):
        """生成设备id"""
        return self.hashfunc.call("ji", t, e)

    def clentinit(self):
        """客户端初始化"""
        with self.macklinSession.get(
            url="https://api.macklin.cn/api/timestamp"
        ) as resp:
            self.ServerTimestamp = self.timestamp = resp.json()["data"]["timestamp"]
            self.macklinSession.headers["X-Timestamp"] = str(self.timestamp)
        l = (
            "x-agent=web&x-language=cn&x-timestamp=%d&salt=ndksyr9834@#$32ndsfu"
            % self.timestamp
        )
        d = "timestamp=%d&salt=ndksyr9834@#$32ndsfu" % int(time.time() * 1000)

        self.sign = self.hash_function(l) + self.hash_function(d)
        self.X_Device_Id = self.generateDeviceid(16, 16)

    def generateSign(self, param: dict):
        """生成Sign"""
        t = re.findall(r"\d", self.sign)
        print(self.sign)
        self.ClentTimestamp = str(int(time.time() * 1000)) + "".join(t)
        self.sign = self.hash_function(
            "x-agent=web&x-language=cn&x-timestamp=%s&salt=ndksyr9834@#$32ndsfu"
            % self.ClentTimestamp
        ) + self.hash_function(
            "&".join(["=".join(map(str, k)) for k in list(param.items())])
            + "&salt=ndksyr9834@#$32ndsfu"
        )

    def browse(self, keyword: str):
        url = "https://api.macklin.cn/api/record/browse"
        json_data = {
            "page": f"/search/{keyword}",
            "pre": f"/search/{keyword}",
            "timestamp": self.ClentTimestamp,
        }
        self.generateSign(json_data)

        self.macklinSession.headers.update(
            {"sign": self.sign, "Referer": "https://www.macklin.cn/search/%s" % keyword}
        )
        with self.macklinSession.post(url=url, json=json_data) as resp:
            print(resp.text)

    def macklinSearch(self, keyword: str, page: int = 1, limit: int = 20):
        """麦克林搜索
        :param keyword: 关键词
        :return: 商品列表
        """
        self.browse(keyword)
        url = "https://api.macklin.cn/api/item/search"
        param = {
            "keyword": keyword,
            "page": page,
            "limit": limit,
            "source": "",
            "timestamp": self.ClentTimestamp,
        }
        self.generateSign(param)

        with self.macklinSession.get(url=url, params=param) as resp:
            print(resp.request.headers)
            return resp.json()
